
/*********************************************************************************
 *      Copyright:  (C) 2022 Zhukaifa（928085237@qq.com）
 *                  All rights reserved.
 *
 *       Filename:  at_cmd.c
 *
 *    Description:   Send the at command to the com port to check whether
 *                   the serial port is available

 *                 
 *        Version:  1.0.0(28/07/22)
 *         Author:  Zhukaifa（928085237@qq.com）
 *      ChangeLog:  1, Release initial version on "28/07/22 21:52:04"
 *                 
 ********************************************************************************/


#include <stdio.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>


#include <string.h>

#include <unistd.h>
#include <fcntl.h>

 
#include <sys/select.h>

#include <termios.h>

#include <unistd.h>
#include "com_func.h"
#include "at_cmd.h"
#include "logger.h"
#define   BUF_SIZE     1024

 
/*********************************************************************************
 *
 *           Name:  at_cmd_send
 *
 *    Description:  Send the AT command to the com port and judge whether
 *                  it is the same as the expected value   
 *
 *        Input args:  
 *                      com:     Structure for storing serial port attributes
 *                      atcmd:   AT command
 *                      expected_recv:    Expected responses
 *                      msgsize:  recv size
 *
 *       Output args: 
 *                      recv:   Store the received reply in recv
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/




int at_cmd_send(comport_t *com, char *atcmd, char *expected_recv, char *recv, int msgsize, int timeout)
{
    char   r_buf[512];

	memset(r_buf, 0, sizeof(r_buf));

    if(!atcmd || !expected_recv)
    {
        printf("Unable to send AT commond,Invalid parameter.\n");
        return -1;
    }

    if(com_send(com->fd, atcmd, strlen(atcmd)) < 0)
    {
        printf("Send AT commond failed:%s\n",strerror(errno));
        return -2;
    }

    usleep(10000);

    if(com_recv(com->fd, r_buf, sizeof(r_buf),timeout) < 0)
    {
        printf("Recving message failed:%s\n",strerror(errno));
        return -3;
    }

    /* Search expectations */

	if(NULL!=strstr(r_buf, expected_recv))
    {
        strncpy(recv,r_buf,msgsize);
	
//		log_info("Success recive:%s\n", recv);
	
    }
     
    return 0;

}

/*********************************************************************************
 *
 *           Name:   check_com_ready 
 *
 *    Description:   Check whether the com port is available       
 *
 *        Input args:      Structure for storing serial port attributes

 *       Output args: 
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/




int check_com_ready(comport_t *com)
{

	int     rv;
	char    buf[32];
	memset(buf, 0, sizeof(buf));

	if(!com)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}


	rv= at_cmd_send(com, "AT\r", "OK", buf, sizeof(buf), 1000);
	if(rv<0)
	{
		log_error("%s function failure", __func__);
		return -1;
	}
	
	
//	log_info("%s, successfully!\n", __func__);
	return 0;

}

/*********************************************************************************
 *
 *           Name:      check_sim_ready
 *
 *    Description:      Check whether the SIM card exists    
 *
 *        Input args:   Structure for storing serial port attributes

 *
 *       Output args: 
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/




int check_sim_ready(comport_t *com)
{

	int     rv;
	char    buf[32];

	if(!com)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}

	memset(buf, 0, sizeof(buf));
	rv= at_cmd_send(com, "AT+CPIN?\r", "READY", buf, sizeof(buf), 3000);
	if(rv<0)
	{

		log_error("%s function failure", __func__);
		return -1;
	}


	memset(buf, 0, sizeof(buf));
	rv= at_cmd_send(com, "AT+CPIN?\r", "ERROR", buf, sizeof(buf), 3000);
	if(rv>0)
	{

		log_warn("error recive:%s\n", buf);
		return 0;
	}

//	log_info("%s, successfully!\n", __func__);

	return 0;

}

/*********************************************************************************
 *
 *           Name:     check_sim_login  
 *
 *    Description:     Check whether the SIM card is registered.
 *                     If the received information is not (0, 1) or (0, 3),
 *                     the SIM card is unavailable      
 *
 *        Input args:   Structure for storing serial port attributes

 *
 *       Output args: 
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/




int check_sim_login(comport_t *com)
{

	int     rv1;
	int     rv2;
	char    buf1[32];
	char    buf2[32];

	if(!com)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}


	memset(buf1, 0, sizeof(buf1));
	rv1= at_cmd_send(com, "AT+CREG?\r", "0,1", buf1, sizeof(buf1), 3000);
	if(rv1<0)
	{

		log_error("%s function failure", __func__);
		return -1;
	}

	memset(buf2, 0, sizeof(buf2));
	rv2= at_cmd_send(com, "AT+CREG?\r", "0,3", buf2, sizeof(buf2), 3000);
	if(rv2<0)
	{

		log_warn("error recive:%s\n", buf2);
		return -2;
	}

	if(rv1&&rv2)//左边是0时整个表达式为零
	{
		log_error("SIM Card is not registered\n");
		return -3;
	}

//	log_info("%s, successfully!\n", __func__);
	return 0;

}
/*********************************************************************************
 *
 *           Name:      check_sim_signal
 *
 *    Description:      Check the signal strength of SIM, 
 *                      [8~31,99] there is a signal available, 
 *                      [99,99] means there is no signal
 *
 *        Input args:   Structure for storing serial port attributes

 *
 *       Output args: 
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/




int check_sim_signal(comport_t *com)
{

	int     rv;
	int     i;
	char    buf[32];

	char    str[32];
	int     str_value;


	if(!com)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}

	memset(buf, 0, sizeof(buf));

	rv= at_cmd_send(com, "AT+CSQ\r", "CSQ", buf, sizeof(buf), 3000);
	if(rv<0)
	{

		log_error("%s function failure", __func__);
		return -1;
	}
	
	for(i=0; i<sizeof(buf); i++)
	{
		if(buf[i] == ',')
		{
			if(buf[i-2] == ' ')//判断逗号前是几位数
			{
 
				strncpy(str, &buf[i-1], 1);
			}
			else
			{
				strncpy(str, &buf[i-2], 2);
			}
		}
	}

	str_value=atoi(str);

	if(str_value<7 || str_value==99)
	{

		printf("Signal Strengh is too low or no signal\n");
        return -2;
	}

//	log_info("%s, successfully!\n", __func__);
	return 0;
}

/*********************************************************************************
 *
 *           Name:     check_sim_allready 
 *
 *    Description:      Check all properties of SIM card  
    
 *
 *        Input args:   Structure for storing serial port attributes

 *
 *       Output args: 
 *
 *      return value:
 *                      =0    success
 *                      <0    failure

 *
 *                 
 ********************************************************************************/



int check_sim_allready(comport_t *com)
{

	if(!com)
	{
		log_error("%s The argument invalid!\n", __func__);
		return -1;
	}

    if(check_com_ready(com) < 0)
        return -1;
    log_info("Serial port ready!\n");


    if(check_sim_ready(com) < 0)
        return -2;
    log_info("SIM card can be detected!\n");


    if(check_sim_login(com) < 0)
        return -3;
    log_info("SIM card is registered!\n");


    if(check_sim_signal(com) < 0)
        return -4;
    log_info("Signal strength meets requirements!\n");

    log_info("\nSIM cards are all ready!\n");

    return 0;
}
